package com.hup.vd.model.config;

import com.alibaba.fastjson.annotation.JSONField;
import com.hup.utils.commons.NameSorter.NamePiece;
import com.hup.utils.commons.NameSorter.NameSortable;
import com.hup.utils.commons.io.BaseConfig;
import com.hup.vd.constant.TaskConstant.TaskState;
import com.hup.vd.service.netSpeed.NetSpeedCounter;
import com.hup.vd.view.customView.TaskItemView;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Date;
import java.util.function.Consumer;

/**
 * 任务数据
 *
 * @author hugan
 * @date 2022/1/9
 */
@Data
@NoArgsConstructor
public class TaskInfo implements BaseConfig<TaskInfo>, NameSortable {

    public static final String TASK_DIR = BaseConfig.Path.getBaseDir() + "task/";
    public static final String EXT = ".task";

    /**
     * 唯一键
     */
    private String uid;
    /**
     * 原html地址
     */
    private String htmlUrl;
    /**
     * 原html标题
     */
    private String htmlTitle;
    /**
     * m3u8地址
     * 创建任务时,如果输入[网页url],则会解释替换成m3u8地址; 只会被成功执行一次
     */
    private String url;
    /**
     * 解密算法,不为空代表需要解密
     *
     * @apiNote 目前仅支持: METHOD=AES-128
     */
    private String decryptMethod;
    /**
     * base64字符串
     */
    private String aesKeyBase64;
    /**
     * hex字符串(32位), 没有0x前缀
     */
    private String aesIvHex;
    /**
     * 文件保存全路径
     */
    private String filePath;
    private Date createTime;

    /**
     * 是否已完成
     */
    private Boolean finished;

    /**
     * 进度,最大值
     */
    private int progressMax;
    /**
     * 进度,当前值
     */
    private int progressValue;
    /**
     * 任务耗时,单位毫秒
     */
    private Long usedTime;
    private Date finishTime;
    /**
     * 文件大小,带单位的;
     * 下载结束后赋值
     */
    private String fileSizeStr;

    //以下是内存字段
    @JSONField(serialize = false)
    private TaskState taskState = TaskState.PAUSE;

    @JSONField(serialize = false)
    private TaskItemView view;

    @JSONField(serialize = false)
    private String shortName;
    //用于文件名排序
    @JSONField(serialize = false)
    private NamePiece namePiece;

    //下载时的字段
    /**
     * 本次下载任务的开始时间
     */
    @JSONField(serialize = false)
    @Setter(value = AccessLevel.PRIVATE)
    private long taskStartTime;
    /**
     * 本次下载任务前的任务耗时
     */
    @JSONField(serialize = false)
    @Setter(value = AccessLevel.PRIVATE)
    private long taskUsedTime0;

    /**
     * ui触发了暂停任务
     */
    @JSONField(serialize = false)
    private boolean waitToPause;
    /**
     * 下载任务结束/暂停后,需要执行的回调
     * 目前只有[删除任务]
     */
    @JSONField(serialize = false)
    private Runnable taskEndCallback;
    /**
     * 下载任务异常中断的异常
     */
    @JSONField(serialize = false)
    private Throwable taskErr;

    /**
     * 进度网格图; 长宽比例恒等于10/1
     *
     */
    @JSONField(serialize = false)
    private BufferedImage progressImage;
    /**
     * 图像宽度,单位:单元格
     * 持久化 仅用于开发观察
     */
    private int progressImageWidth;

    /**
     * 下载速度
     */
    @JSONField(serialize = false)
    private NetSpeedCounter netSpeedCounter = new NetSpeedCounter();

    public TaskInfo(String uid) {
        this.uid = uid;
    }

    @Override
    public String configPath() {
        return TASK_DIR + uid + EXT;
    }

    public void useView(Consumer<TaskItemView> consumer) {
        if (view != null) consumer.accept(view);
    }

    @JSONField(serialize = false)
    public boolean getFinishedState() {
        return Boolean.TRUE.equals(finished);
    }

    /**
     * true-非[已暂停, 已完成]
     */
    @JSONField(serialize = false)
    public boolean isRunning() {
        return !(taskState == TaskState.PAUSE || taskState == TaskState.FINISHED);
    }

    /**
     * 任务启动前,初始化字段
     */
    public void initAtTaskStart() {
        waitToPause = false;
        taskEndCallback = null;
        taskErr = null;
        taskUsedTime0 = usedTime == null ? 0 : usedTime;
        taskStartTime = System.currentTimeMillis();
    }

    /**
     * 更新任务耗时
     */
    public void updateUsedTime() {
        long currentUsedTime = System.currentTimeMillis() - taskStartTime;
        usedTime = taskUsedTime0 + currentUsedTime;
    }

    @JSONField(serialize = false)
    public File getTempDirFile() {
        File targetFile = new File(filePath);
        String tempDirName = targetFile.getName().replace(".", "");
        return new File(targetFile.getParent(), tempDirName);
    }

    @Override
    @JSONField(serialize = false)
    public String getSortName() {
        return shortName;
    }

    @Override
    public String toString() {
        return "TaskInfo{" + filePath + "}";
    }
}
